﻿package projects {
	import extremefx.anim.Tween;
	import extremefx.browser.FlashVars;
	import extremefx.browser.ResizeFlash;
	import extremefx.events.EventArgs;
	import extremefx.events.Events;

	import projects.flashUpload.Item;
	import projects.flashUpload.Upload;

	import flash.display.MovieClip;
	import flash.display.SimpleButton;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.net.FileFilter;
	import flash.net.FileReference;
	import flash.net.FileReferenceList;
	import flash.system.Security;
	import flash.text.TextField;
	import flash.text.TextFieldAutoSize;

	/**
	 * @author Marcelo Volmaro
	 */

	[Frame(factoryClass="extremefx.Preloader")];
	public final class FlashUpload extends Sprite {
		private var _sizeUnits:Array = [ "Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB" ];

		private var _info:MovieClip;
		private var _fileBrowserMany:FileReferenceList = new FileReferenceList();
		private var _fileList:Array = [];

		private var _filesTxt:TextField;
		private var _uploadedTxt:TextField;

		private var _addFiles:SimpleButton;
		private var _clearFiles:SimpleButton;
		private var _uploadFiles:SimpleButton;
		private var _uploading:Boolean;


		private var _actualSize:Number;
		private var _totalSize:Number;
		private var _totalFiles:uint;

		private var _currentItem:Item;
		private var _uploadUrl:String;
		private var _uploadVars:Object;
		private var _oldStageWidth:uint;
		private var _statusok:MovieClip;

		public function main():void{
			FlashVars.init(this);

			Security.allowDomain("*");	// Allow uploading to any domain
			Security.allowInsecureDomain("*");	// Allow uploading from HTTP to HTTPS and HTTPS to HTTP

//			_uploadUrl = FlashVars.getValue("uploadUrl", "/Upload.axd");			_uploadUrl = FlashVars.getValue("uploadUrl", "http://localhost:1966/GpiUpload.axd");
//			_uploadUrl = FlashVars.getValue("uploadUrl", "http://test.globalizationpartners.com/GpiUpload.axd");
			_uploadVars = loadPostParams(FlashVars.getValue("postParams"));
			_fileBrowserMany.addEventListener(Event.SELECT, selectManyHandler);
			_info = new Info_mc();
			addChild(_info);

			var addFiles:SimpleButton = _addFiles = _info.add_btn;
			addFiles.addEventListener(MouseEvent.CLICK, addFilesHandler);

			var clearFiles:SimpleButton = _clearFiles = _info.clear_btn;
			clearFiles.addEventListener(MouseEvent.CLICK, clearFilesHandler);

			var uploadFiles:SimpleButton = _uploadFiles = _info.upload_btn;
			uploadFiles.addEventListener(MouseEvent.CLICK, uploadFilesHandler);

			_filesTxt = _info.files_txt;
			_uploadedTxt = _info.uploaded_txt;
			_filesTxt.autoSize = _uploadedTxt.autoSize = TextFieldAutoSize.LEFT;
			_statusok = _info.statusok_mc;
			_statusok.visible = false;

			stage.addEventListener(Event.RESIZE, _resize);

			updateInfo();
			_resize();
		}

		private function _uploadEnabled(pEnable:Boolean):void {
			_uploadFiles.enabled = pEnable;
			_uploadFiles.alpha = pEnable ? 1 : .2;
		}

		private function uploadFilesHandler(event:MouseEvent):void {
			_uploadEnabled(false);
			_addFiles.enabled = _clearFiles.enabled = false;
			_addFiles.alpha = _clearFiles.alpha = .2;
			_uploading = true;
			_actualSize = 0;
			_nextItem();
		}

		private function _nextItem():void {
			_currentItem = _fileList[0];

			if (_currentItem){
				Events.add(_currentItem.OnRemove, _getNext);
				_currentItem.upload.start(_uploadUrl, _uploadVars);

			} else {
				_uploading = false;
				_addFiles.enabled = _clearFiles.enabled = true;
				_addFiles.alpha = _clearFiles.alpha = 1;
				clearFilesHandler(null);

				_statusok.visible = true;
				_statusok.alpha = 0;
				Tween.animate(_statusok).setProperty("alpha", 1);
			}

			updateInfo();
		}

		private function _getNext(pItem:EventArgs):void {
			_actualSize += pItem.eventTarget.upload.size;
			pItem.eventTarget.dispose();
			_nextItem();
		}

		private function clearFilesHandler(event:MouseEvent):void {
			for each(var item:Item in _fileList){
				item.remove(0);
			}

			_actualSize = _totalSize = _totalFiles = 0;
			_fileList = [];
			updateInfo();
		}

		private function addFilesHandler(event:MouseEvent):void {
			var t:Array = FlashVars.getValue("fileTypes", "All Files:*.*").split(",");
			var filters:Array = [];

			for (var i:int = 0; i<t.length; i++){
				var parts:Array = t[i].split(":");

				var f:FileFilter = new FileFilter(parts[0], parts[1]);
				filters.push(f);
			}

			_fileBrowserMany.browse(filters);
		}

		private function selectManyHandler(event:Event):void {
			var list:Array = _fileBrowserMany.fileList;
			var w:uint = this.stage.stageWidth;

			var fll:int = _fileList.length;
			var lastY:uint;

			if (fll > 0){
				var item:Item = _fileList[fll-1];
				lastY = item.y + item.height;

			} else {
				lastY = 48;
			}

			for (var i:int = 0; i < list.length; i++){
				var fr:FileReference = list[i];
				if (fr.size < 1) continue;//do not allow uploads of 0 bytes.

				item = new Item(new Upload(fr), _info);
				_fileList.push(item);
				item.y = lastY;
				item.width = w;
				Events.add(item.OnRemove, _onRemove);
				lastY += item.height;
			}

			_statusok.visible = false;
			updateInfo();
		}

		private function updateInfo():void {
			if (!_uploading){
				var totalSize:Number = 0;
				var totalFiles:uint = 0;
				for each(var item:Item in _fileList){
					totalFiles++;
					totalSize += item.upload.size;
				}

				_filesTxt.text = "Total Files: " + totalFiles + "\rTotal size: "+ toHumanSize(totalSize);
				_totalSize = totalSize;
				_totalFiles = totalFiles;
				_uploadEnabled(_fileList.length != 0);
			}

			_uploadedTxt.text = "Uploaded: "+(int(_actualSize/_totalSize*10000)/100)+"%\rUploaded: "+toHumanSize(_actualSize)+" of "+ toHumanSize(_totalSize);

			if (_fileList.length){
				var lastItem:Item = _fileList[_fileList.length-1];
				ResizeFlash.setSize(0, lastItem.y + lastItem.height + 2);

			} else {
				ResizeFlash.setSize(0, 82);
			}
		}

		private function toHumanSize(pSize:Number):String {
			var index:uint = 0;
			while (pSize >= 1000){
				pSize /= 1000;
				index++;
			}

			pSize = int(pSize * 100)/100;

			return String(pSize + " "+_sizeUnits[index]);
		}

		private function _onRemove(pEventArgs:EventArgs):void {
			var item:Item = Item(pEventArgs.eventTarget);
			var i:int = _fileList.indexOf(item);
			if (i == -1) return;

			_fileList.splice(i, 1);
			var lastY:uint = item.y;
			if (!_uploading) item.dispose();

			for (; i < _fileList.length; i++){
				item = _fileList[i];
				item.y = lastY;
				lastY += item.height;
			}

			updateInfo();
		}

		private function _resize(event:Event = null):void {
			var w:uint = this.stage.stageWidth;
			if (_oldStageWidth == w) return;

			_oldStageWidth = w;
			_uploadFiles.x = w - _uploadFiles.width;
			_statusok.x = int((w - _statusok.width)/2);

			for each(var item:Item in _fileList){
				item.width = w;
			}
		}

		private function loadPostParams(param_string:String):Object {
			var post_object:Object = {};

			if (param_string != null) {
				var name_value_pairs:Array = param_string.split("&amp;");

				for (var i:Number = 0; i < name_value_pairs.length; i++) {
					var name_value:String = String(name_value_pairs[i]);
					var index_of_equals:Number = name_value.indexOf("=");
					if (index_of_equals > 0) {
						post_object[decodeURIComponent(name_value.substring(0, index_of_equals))] = decodeURIComponent(name_value.substr(index_of_equals + 1));
					}
				}
			}

			return post_object;
		}
	}
}